package com.gome.ss.flowcrawl.extractor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.gome.ss.common.AppConfiguer;
import com.gome.ss.core.plugin.Plugin;
import com.gome.ss.core.plugin.PluginManager;
import com.gome.ss.core.plugin.SpiderLocalPluginHandle;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public class FlowCrawlExtractorManager {
	private static Logger logger = Logger.getLogger(FlowCrawlExtractorManager.class);
	
	static {
		FlowCrawlExtractorIndexDataListener.createListener();
	}
	
	public static final String scriptFunctionPrefix = "prefix_";
	public static final String collectionNameSuffix = "_data";
	public static final String mqprefix = "flowcrawl-";
	public static final String esdqName = "FlowCrawlESDataQueue";
	public static final String extractDataFacetKey = "extractDataFacetKeyFields";
	
	public static final int NormalTaskType = 0;
	public static final int IncrementalTaskType = 1;
	public static final int FilterTaskType = 2;
	public static final int DoIndexTaskType = 3;
	
	private static final String filterDicSuffix = "-filter.dic";
	private static FlowCrawlExtractorManager instance = null;
	
	private Map<String, FlowCrawlExtractor> extractorMap = new HashMap<String, FlowCrawlExtractor>();
	
	public static FlowCrawlExtractorManager getInstance() {
		if (instance == null)
			instance = new FlowCrawlExtractorManager();
		return instance;
	}
	
	public static String getFilterDicFilePathName(String name) {
		return AppConfiguer.getStringByKey("htmlFilterDicDir") + "/" + name + filterDicSuffix;
	}
	
	private String constructRequestString(String name, String stepID) {
		return name + "=##=" + stepID;
	}
	
	/**
	 * 
	 * @param name
	 * @param stepID
	 * @return -4 正在爬取，无法提取; -3 启动失败; -2 没有这个提取器配置; -1 已经开始; 0 开始;
	 */
	public int start(String name, String stepID, int taskType) {
		String requestString = constructRequestString(name, stepID);
		
		if (taskType == NormalTaskType) {
			List<Plugin> plugins = PluginManager.getInstance().getPlugin(name);
			for (Plugin plugin : plugins) {
				SpiderLocalPluginHandle handle = (SpiderLocalPluginHandle) plugin.getHandle();
				if (plugin.getHandle().processable() && plugin.getTaskProcess().checkProcessing()) {
					logger.error(handle.getPluginQualifiedName() + " is processing!");
					return -4;
				}
			}
		}
		
		FlowCrawlExtractorConfig config = getConfig(name, stepID);
		if (config == null) {
			logger.error(name + " have no config.");
			return -2;
		}
		
		FlowCrawlExtractor extractor = null;
		
		if (extractorMap.containsKey(requestString)) {
			extractor = extractorMap.get(requestString);
			extractor.setConfig(config);
			if (extractor.getStatus().getStatus() == FlowCrawlExtractorStatus.STATUS_START) {
				logger.error(name + " already stared.");
				return -1;
			}
		} else {
			extractor = new FlowCrawlExtractor();
			extractor.setConfig(config);
			extractor.startParser();
			extractorMap.put(requestString, extractor);
		}
		
		if (taskType == FilterTaskType) {
			extractor.setTask(new FlowCrawlExtractorFilterTask(extractor));
		} else if (taskType == IncrementalTaskType || taskType == NormalTaskType) {
			if (taskType == IncrementalTaskType) {
				extractor.setTask(new FlowCrawlExtractorIncrementalTask(extractor));
			} else if (taskType == NormalTaskType){
				extractor.setTask(new FlowCrawlExtractorNormalTask(extractor));
			}
		} else if (taskType == DoIndexTaskType) {
			extractor.setTask(new FlowCrawlExtractorDoIndexTask(extractor));
		}
		
		if (extractor.start()) {
			logger.info(name + " start extract data.");
			return 0;
		}
		
		return -3;
	}
	
	public FlowCrawlExtractor buildForRandomExtractor(String name, String stepID) {
		FlowCrawlExtractorConfig config = getConfig(name, stepID);
		if (config == null) {
			logger.error(name + " have no config.");
			return null;
		}
		
		return FlowCrawlExtractor.newRandomExtractor(config);
	}
	
	public void stop(String name, String stepID) {
		FlowCrawlExtractor extractor = getExtractor(name, stepID);
		if (extractor == null)
			return;
		
		FlowCrawlExtractorTask task = extractor.getTask();
		if (task == null)
			return;
		
		task.stop();
	}
	
	public void remove(String name, String stepID) {
		String requestString = constructRequestString(name, stepID);
		if (extractorMap.containsKey(requestString))
			extractorMap.remove(requestString);
	}
	
	public FlowCrawlExtractor getExtractor(String name, String stepID) {
		String requestString = constructRequestString(name, stepID);
		if (extractorMap.containsKey(requestString)) 
			return extractorMap.get(requestString);
		return null;
	}
	
	private FlowCrawlExtractorConfig getConfig(String name, String stepID) {
		BasicDBObject query = new BasicDBObject("name", name);
		query.append("stepID", stepID);
		DBCollection collection = AppConfiguer.flowCrawlConfigMongo.getDB(AppConfiguer.FLOWCRAWL_DB_NAME)
				 .getCollection(AppConfiguer.FLOWCRAWL_EXTRACT_COLLECTION_NAME);
		DBCursor cursor = collection.find(query);
		
		List<DBObject> array = new ArrayList<DBObject>();
		
		while(cursor.hasNext()) {
			DBObject obj = cursor.next();
			return new FlowCrawlExtractorConfig(obj);
		}
		
		return null;
	}
}
